from abc import ABC, abstractmethod
from typing import List, Optional


# ABC = Abstract Class 抽象类
# 抽象类，只定义方法，但是不实现具体的方法
# 具体的方法，放在了各个具体的子类当中去实现。
# 就是OOP当中的抽象概念，相当于 人类 这是一个抽象的概念，但是所有人，不管黑人白人，都会吃饭
# 后续基本不会用到基类，基类只是起到了一个奠基的作用

class SimilarityBase(ABC):

    @abstractmethod
    def get_similarity_score(self, str1: str, str2: str) -> float:
        """
        计算两个字符串的相似度分数

        :param str1: 第一个字符串
        :param str2: 第二个字符串
        :return: 两个字符串之间的相似度分数
        """
        pass

    def find_best_match(self, target: str, candidates: List[str], top_n: Optional[int] = 1) -> List[str]:
        """
        在候选字符串中找到最匹配的字符串。

        :param target: 目标字符串
        :param candidates: 候选字符串列表
        :param top_n: 返回最匹配的前 N 个结果，默认为 1
        :return: 最匹配的字符串列表
        """
        if not candidates:
            raise ValueError('Candidates cannot be empty')

        # 计算每个候选字符串的相似度分数
        scored_matches = []
        for candidate in candidates:
            try:
                score = self.get_similarity_score(target, candidate)
                scored_matches.append((candidate, score))
            except Exception as e:
                raise RuntimeError(f"计算相似度时出现错误: {e}")

        # 按分数排序，返回前 top_n 个匹配结果
        scored_matches.sort(key=lambda x: x[1], reverse=True)
        best_matches = [match[0] for match in scored_matches[:top_n]]
        return best_matches

    @staticmethod
    def validate_strings(str1: str, str2: str) -> None:
        """
        校验两个字符串是否符合计算条件。

        :param str1: 第一个字符串
        :param str2: 第二个字符串
        :return: 校验是否通过
        """
        if not isinstance(str1, str) or not isinstance(str2, str):
            raise ValueError("输入值必须是字符串类型！")

        if not str1 or not str2:
            raise ValueError("字符串不能为空！")
